#pragma once

#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <unordered_map>
#include <sstream>
#include <iomanip>
#include <cctype>
#include "Log.hpp"

// #define OK 200
// #define MOVED_PERMANENTLY 301
// #define FOUND 302
// #define SEE_OTHER 303
// #define NOT_MODIFIED 304
// #define TEMPORARY_REDIRECT 307
// #define BAD_REQUEST 400
// #define NOT_FOUND 404
// #define SERVER_ERROR 500

enum
{
    OK = 200,
    MOVED_PERMANENTLY = 301,
    FOUND = 302,
    SEE_OTHER = 303,
    NOT_MODIFIED = 304,
    TEMPORARY_REDIRECT = 307,
    BAD_REQUEST = 400,
    FORBIDDEN = 403,
    NOT_FOUND = 404,
    SERVER_ERROR = 500
};
// 工具类
class Util
{
public:
    // 读取http 请求一行数据 返回读取的长度
    static int ReadLine(int _sockFd, std::string &out)
    {
        // 兼容各种http报文结尾分隔符
        // \r -> \n; \n -> \n; \r\n -> \n;
        char ch = 'X';
        while (ch != '\n')
        {
            // ssize_t recv(int sockfd, void *buf, size_t len, int flags);
            ssize_t readBytes = recv(_sockFd, &ch, 1, 0);
            if (readBytes > 0)
            {
                if (ch == '\r')
                {
                    recv(_sockFd, &ch, 1, MSG_PEEK);
                    if (ch == '\n')
                    {
                        // \r\n -> \n
                        recv(_sockFd, &ch, 1, 0);
                    }
                    else
                    {
                        // \r -> \n
                        ch = '\n';
                    }
                }
                // X -> X; \n -> \n
                out.push_back(ch);
            }
            else if (readBytes == 0)
            {
                // 客户端关闭连接
                LOG(WARNING, "client close");
                return 0;
            }
            else
            {
                // 读取错误
                LOG(ERROR, "recv error");
                return -1;
            }
        }
        return out.size();
    }

    // 将target字符串按照sep分割成两个子串sub1_out和sub2_out
    static bool CutString(const std::string &target, std::string &sub1_out, std::string &sub2_out, std::string sep)
    {
        size_t pos = target.find(sep);
        if (pos != std::string::npos)
        {
            sub1_out = target.substr(0, pos);
            sub2_out = target.substr(pos + sep.size());
            return true;
        }
        return false;
    }

    // 将http响应状态码转换为描述
    static std::string statusCodeToDesc(int code)
    {
        // 改为哈希
        static std::unordered_map<int, std::string> statusCodeMap = {
            {OK, "OK"},
            {MOVED_PERMANENTLY, "Moved Permanently"},
            {FOUND, "Found"},
            {SEE_OTHER, "See Other"},
            {NOT_MODIFIED, "Not Modified"},
            {TEMPORARY_REDIRECT, "Temporary Redirect"},
            {FORBIDDEN, "Forbidden"},
            {BAD_REQUEST, "Bad Request"},
            {NOT_FOUND, "Not Found"},
            {SERVER_ERROR, "Internal Server Error"}};

        auto iter = statusCodeMap.find(code);
        if (iter != statusCodeMap.end())
        {
            return iter->second;
        }
        return "Unknown Status Code";
    }

    // 将文件后缀转换为具体正文类型
    static std::string reqPathSuffixToDesc(const std::string &suffix)
    {
        static std::unordered_map<std::string, std::string> suffixMap = {
            {".html", "text/html"},
            {".css", "text/css"},
            {".js", "application/javascript"},
            {".jpg", "application/x-jpg"},
            {".png", "application/x-png"},
            {".gif", "application/x-gif"},
            {".ico", "application/x-ico"},
            {".json", "application/json"},
            {".xml", "application/xml"}};

        auto iter = suffixMap.find(suffix);
        if (iter != suffixMap.end())
        {
            return iter->second;
        }
        return "text/html";
    }

    static bool GetReqParam(std::string &reqParam)
    {
        bool result = false;
        std::string method = getenv("METHOD");
        if (method == "GET")
        {
            reqParam = getenv("REQ_PARAM");
            result = true;
        }
        else if (method == "POST")
        {
            int content_length = atoi(getenv("CONTENT_LENGTH"));
            char c = 0;
            while (content_length)
            {
                read(0, &c, 1);
                reqParam.push_back(c);
                content_length--;
            }
            /*
            std::string postData;
            postData.resize(reqBodyLen);
            std::cin.read(&postData[0], reqBodyLen); // istream& read (char* s, streamsize n);
            */
            result = true;
        }
        else
        {
            result = false;
        }
        return result;
    }

    static void printLog(const std::string &logMessage)
    {
        std::time_t currentTime = std::time(nullptr);      // 获取当前时间
        std::tm *localTime = std::localtime(&currentTime); // 转换为本地时间

        std::cout << "$$$$$$$$$$$$$$$$$$$$$$$$$$" << logMessage << " $$$$$$$$$$ "
                  << localTime->tm_hour << ":" // 时
                  << localTime->tm_min << ":"  // 分
                  << localTime->tm_sec         // 秒
                  << " $$$$$$$$$$\n";
    }

    // URL 编码函数
    static std::string UrlEncode(const std::string &str)
    {
        std::ostringstream escaped;
        escaped.fill('0');
        escaped << std::hex;

        for (size_t i = 0; i < str.length(); ++i)
        {
            char c = str[i];
            // 处理不可打印的字符
            if (std::isalnum(c) || c == '-' || c == '_' || c == '.' || c == '~')
            {
                escaped << c;
            }
            else
            {
                escaped << '%' << std::uppercase << std::setw(2) << int((unsigned char)c);
            }
        }
        return escaped.str();
    }

    static std::string UrlDecode(const std::string &encoded)
    {
        std::string decoded;
        size_t length = encoded.length();

        for (size_t i = 0; i < length; ++i)
        {
            if (encoded[i] == '%')
            {
                // 如果是%符号，则接下来的两个字符是十六进制值
                if (i + 2 < length && isxdigit(encoded[i + 1]) && isxdigit(encoded[i + 2]))
                {
                    // 转换%后面的两位十六进制字符
                    std::string hexStr = encoded.substr(i + 1, 2);
                    char decodedChar = static_cast<char>(std::stoi(hexStr, nullptr, 16));
                    decoded += decodedChar;
                    i += 2; // 跳过已处理的两个字符
                }
                else
                {
                    // 如果没有有效的十六进制字符，直接加%符号
                    decoded += encoded[i];
                }
            }
            else if (encoded[i] == '+')
            {
                // "+"替代空格
                decoded += ' ';
            }
            else
            {
                // 其他字符直接添加到解码结果中
                decoded += encoded[i];
            }
        }

        return decoded;
    }
};
